#include "common.h"

#include "base/html_escape.h"

#include "im/adapters/session_adapter.h"
#include "im/adapters/message_outlet_adapter.h"
#include "im/adapters/message_history_adapter.h"
#include "im/adapters/recent_contact_adapter.h"

namespace imserver {

int DispatchDefaultMessage(ImMessage & message) {
  SessionList session_list;
  
  if (0 != SessionAdapter::Instance().GetSessionList(message.receiver, &session_list, 2)) {
    LOG_WARN("GetSessionList error, receiver=" << message.receiver);
  }

  int count = 0;
  if (session_list.empty()) {
    SessionList sender_sessions;
    SessionAdapter::Instance().GetSessionList(message.sender, &sender_sessions, 2);

    ImMessage notify_message;
    if (message.__isset.via_shop) {
      LOG_INFO("offline notify from via_shop " << message.via_shop);
      notify_message.sender = message.via_shop;
    } else {
      notify_message.sender = message.receiver;
    }
    notify_message.receiver = message.sender;
    notify_message.timestamp = time(NULL);

    if (message.receiver > IM_TEMP_ID_BASE) {
      int64_t qid = SessionAdapter::Instance().GetQidByTempId(message.receiver);

      if (qid > 0) {
        SetMessageType(notify_message, MSG_TYPE_LOGIN_NOTIFY);
        std::string username(GetUsername(qid));

        std::stringstream body;
        body << "<span class=\"icon-error\"></span>消息发送失败！此用户已经登录360账号<b>"
             << base::HtmlEscape(username)
             << "</b>，<a href=\"#nogo\" class=\"resend-chguser-msg\" data-id=\"" << qid 
             << "\">点此发送该消息给<b>" << base::HtmlEscape(username) << "</b></a>"
             << "<span class=\"msg-send-failed\" style=\"display:none\">"
             << base::HtmlEscape(message.body)
             << "</span>";
        notify_message.body = body.str();
      } else {
        SetMessageType(notify_message, MSG_TYPE_OFFLINE_NOTIFY);
        std::stringstream body;
        body << GetDefaultUsername(message.receiver) << "不在线，下次上线会收到您的消息。";
        notify_message.body = body.str();
      }
    } else{
      SetMessageType(notify_message, MSG_TYPE_OFFLINE_NOTIFY);
      if (message.__isset.via_shop) {
        std::stringstream body;
        body << "可能由于网络原因，消息\"<b>" << message.body << "</b>\"发送失败，请稍后重试";
        notify_message.body = body.str();
      } else {
        notify_message.body = "对方可能不在线，上线后会收到您的消息";
      }
    }
    for(size_t i = 0; i < sender_sessions.size(); ++i) {
      int res = MessageOutletAdapter::Instance().DistributeMessage(sender_sessions[i].key, notify_message, 2);
      LOG_DEBUG("notify message type=" << MessageType(notify_message) << message.receiver << " reveiver=" 
               << notify_message.receiver << " res=" << res);
    }
    LOG_INFO("message " << message.seq_id << " sender=" << message.sender << " receiver=" << message.receiver << " stored.");
  } else {
    if (message.flags & MSG_FLAG_RECREATE_ON_LINGER) {
      // 有其他副本在线，不需要RECREATE_ON_LINGER
      LOG_INFO("receiver " << message.receiver << " other session online, RECREATE_ON_LINGER not required");
      return 0;
    }

    for(size_t i = 0; i < session_list.size(); ++i) {
      if (session_list[i].timestamp - time(NULL) > 300) {
        // TODO : remove stale session
        LOG_WARN("session " << session_list[i].key << " timeout!");
        continue;
      }
      if (MessageOutletAdapter::Instance().DistributeMessage(session_list[i].key, message, 2) == 0) {
        LOG_DEBUG("DistributeMessage ok. sender=" << message.sender << " receiver=" << message.receiver << " session=" << session_list[i].key);
        ++count;
      } else {
        LOG_WARN("DistributeMessage err. sender=" << message.sender << " receiver=" << message.receiver << " session=" << session_list[i].key);
      }
    }
    if (count > 0) {
      message.flags |= MSG_FLAG_READ;
    }
    LOG_INFO("message " << message.seq_id << " sender=" << message.sender << " receiver=" << message.receiver << " delivery=" << count);
  }
  if (message.seq_id > 0) {
    MessageHistoryAdapter::Instance().AddMessage(message, 2);
  }
  RecentContactAdapter::Instance().Add(message.sender, message.receiver, 2);
  return 0;
}

}

